package org.javahispano.javacup.tacticas_aceptadas.FGR.javacup2009.gallegux.javacup2009.canelaenrama;



import org.javahispano.javacup.tacticas_aceptadas.FGR.javacup2009.gallegux.javacup2009.canelaenrama.ed.DoubleDouble;
import org.javahispano.javacup.tacticas_aceptadas.FGR.javacup2009.gallegux.javacup2009.canelaenrama.ed.IntDoubleDouble;
import org.javahispano.javacup.tacticas_aceptadas.FGR.javacup2009.gallegux.javacup2009.canelaenrama.ed.IntDoubleDoubleDouble;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.javahispano.javacup.modelo.Constantes;



public class Tiros 
{
	
	final double INCR_FUERZA = 0.05;
	final double INCR_ANGULO = 0.5;
	final double INCR_ANGULO_TIROS_RASOS = 0.1;
	

	HashMap<DoubleDouble, DoubleDouble> tirosPorteriaAlto = null; // tiros a porteria por encima del portero
	HashMap<DoubleDouble, DoubleDouble> pasesJugador = null; // pases a jugador por encima de otros jugadores
	HashMap<DoubleDouble, DoubleDouble> pasesJugadorAltos = null; // pases a jugador por encima de otros jugadores
	
	
	
	
	public Tiros()
	{
		tirosPorteriaAlto = generar(Constantes.ALTO_ARCO, Constantes.ALTO_ARCO);
//		log.info("------------TIROS------------");
//		print(tirosPorteria);

		pasesJugador = generar(Constantes.ALTURA_CONTROL_BALON, Constantes.ALTURA_CONTROL_BALON);
//		log.info("------------PASES------------");
//		print(pasesJugador);
		
//		tirosPorteriaRasos = generarTirosRasos();
//		log.info("------------TIROS 'RASOS'------------");
//		print(tirosPorteriaRasos);
		
		pasesJugadorAltos = generar(6.0, Constantes.ALTURA_CONTROL_BALON);
		
		//log.info("tama�o listas=" + tirosPorteriaAlto.size() + " " + pasesJugador.size());
	}
	
	
	
	/**
	 * 
	 * @param minAlturaAlcanzar altura minima que debe alcanzar
	 * @param alturaControlCaida altura a la que se controlara
	 * @return
	 */
	private HashMap<DoubleDouble, DoubleDouble> generar(double minAlturaAlcanzar, double alturaControlCaida)
	{
		HashMap<DoubleDouble, DoubleDouble> map = 
			new HashMap<DoubleDouble, DoubleDouble>();
		PosicionBalon posBalonAnt = null;
		PosicionBalon posBalonAct = null;
		TrayectoriaBalon trayectoriaBalon = null;
		List<PosicionBalon> posicionesTrayectoria = null;
		boolean fin = false;
		String s;
		
		for (double fuerza = INCR_FUERZA; fuerza <= 1.0; fuerza += INCR_FUERZA) {
			for (double angulo = 0; angulo <= Constantes.ANGULO_VERTICAL_MAX; angulo += INCR_ANGULO) {

				trayectoriaBalon = new TrayectoriaBalon(fuerza, angulo);
				s = "";

				if (trayectoriaBalon.isTiroAlto(minAlturaAlcanzar)) {
					posicionesTrayectoria = trayectoriaBalon.getPosiciones();
					fin = false;
					
					for (int i = 1; !fin && i < posicionesTrayectoria.size(); i++) {
						posBalonAnt = posicionesTrayectoria.get(i-1);
						posBalonAct = posicionesTrayectoria.get(i);
						s += posBalonAct.toStringPosicion() + " ";
						
						if (posBalonAct.getZ() <= alturaControlCaida && posBalonAnt.getZ() > alturaControlCaida) {
							DoubleDouble parDistDist = new DoubleDouble(posBalonAnt.getX(), posBalonAct.getX());
							DoubleDouble parFuerzaAngulo = new DoubleDouble(fuerza, angulo);
							map.put(parFuerzaAngulo, parDistDist);
							fin = true;
//							log.info(parFuerzaAngulo + " " + parDistDist + " --> " + s + "dist: " + 
//									new Posicion(0,0).distancia(posBalonAct.getPosicion())+"");
						}
						
					}
				}
			}
		}
		
		return map;
	}
	
	
	
	/**
	 * int=iteraciones
	 * double1=distancia antes del suelo
	 * double2=distancia en el suelo
	 * double3=angulo
	 * @return
	 */
	public void generarTirosRasos()
	{
		TrayectoriaBalon trayectoriaBalon;
		IntDoubleDouble iteDist;
		
		for (double angulo = 0; angulo <= Constantes.ANGULO_VERTICAL_MAX; angulo += INCR_ANGULO_TIROS_RASOS) {
			trayectoriaBalon = new TrayectoriaBalon(1.0, angulo);
			iteDist = trayectoriaBalon.buscarIteracionSuelo();
			if (null != iteDist) {
				System.out.println(iteDist.integer+" "+Util.toString(iteDist.double1)+" "+Util.toString(iteDist.double2)+" "+Util.toString(angulo));
			}
		}
	}
	
	
	
	/**
	 * busca el angulo vertical mas rapido para un tiro raso
	 * los datos se sacan del metodo generarTirosRasos()
	 * @param distancia
	 * @return
	 */
	public double getAnguloVerticalTiroRaso(double distancia)
	{
		//datos obtenidos a mano
		
		if (distancia < 15.241) {
			return 7.3;
		}
		else if (distancia < 18.871) {
			return 10.3;
		}
		else if (distancia < 22.161) {
			return 13.4;
		}
		else if (distancia < 25.051) {
			return 16.7;
		}
		else {
			return -1;
		}
	}
	
	
	
	/**
	 * devuelve un par (fuerza,angulo)
	 */
	public DoubleDouble getTiro(double distancia)
	{
		return buscarParFuerzaAngulo(distancia, tirosPorteriaAlto, true);
	}
	
	
	
	public DoubleDouble getPaseAlto(double distancia)
	{
		return buscarParFuerzaAngulo(distancia, pasesJugadorAltos, false);
	}
	
	
	
	public DoubleDouble getPase(double distancia)
	{
		return buscarParFuerzaAngulo(distancia, pasesJugador, false);
	}
	
	
	
	private DoubleDouble buscarParFuerzaAngulo(double distancia, HashMap<DoubleDouble, DoubleDouble> tiros, boolean masRapido)
	{
		Set<DoubleDouble> claves = tiros.keySet();
		Iterator<DoubleDouble> iClaves = claves.iterator();
		DoubleDouble mejor = new DoubleDouble(0,0);
		
		while (iClaves.hasNext()) {
			DoubleDouble parFuerzaAngulo = iClaves.next();
			DoubleDouble parDistDist = tiros.get(parFuerzaAngulo);
			
			if (parDistDist.double1 < distancia && distancia < parDistDist.double2) {
				//log.info("distancia: " + distancia + "  par: " + parDistDist);
				if (masRapido) {
					if (parFuerzaAngulo.double1 > mejor.double1) {
						mejor.double1 = parFuerzaAngulo.double1;
						mejor.double2 = parFuerzaAngulo.double2;
					}
				}
				else {
					return parFuerzaAngulo;
				}
			}
		}
		
		return (mejor.double1 != 0) ? mejor : null;
	}
	
	
	
	public void print(HashMap<DoubleDouble, DoubleDouble> datos)
	{
		Set<DoubleDouble> claves = datos.keySet();
		Iterator<DoubleDouble> iClaves = claves.iterator();
		DoubleDouble parFuerzaAngulo = null;
		DoubleDouble parDistDist = null; 

		while (iClaves.hasNext()) {
			parFuerzaAngulo = iClaves.next();
			parDistDist = datos.get(parFuerzaAngulo);

		}
	}
	
	
	public void print(List<IntDoubleDoubleDouble> tirosRasos)
	{
		Iterator<IntDoubleDoubleDouble> iteC = tirosRasos.iterator();
		IntDoubleDoubleDouble cuarteto = null;
		
		while (iteC.hasNext()) {
			cuarteto = iteC.next();
		}
	}
	

	
//	public static void main(String...a)
//	{
//		new Tiros().generarTirosRasos();
//	}
	
	
}
